<script lang="ts" setup>
  import { computed, unref, watch, nextTick, ref } from 'vue'
  import { ElIcon } from 'element-plus'
  import { propTypes } from '@/utils/propTypes'
  import Iconify from '@purge-icons/generated'
  import { useDesign } from '@/hooks/web/useDesign'

  defineOptions({ name: 'Icon' })

  const { getPrefixCls } = useDesign()

  const prefixCls = getPrefixCls('icon')

  const props = defineProps({
    // icon name
    icon: propTypes.string,
    // icon color
    color: propTypes.string,
    // icon size
    size: propTypes.number.def(16),
    // icon svg class
    svgClass: propTypes.string.def('')
  })

  const elRef = ref<HTMLElement | null>(null)

  const isLocal = computed(() => props.icon.startsWith('svg-icon:'))

  const symbolId = computed(() => {
    return unref(isLocal) ? `#icon-${props.icon.split('svg-icon:')[1]}` : props.icon
  })

  const getIconifyStyle = computed(() => {
    const { color, size } = props
    return {
      fontSize: `${size}px`,
      height: '1em',
      color
    }
  })

  const getSvgClass = computed(() => {
    const { svgClass } = props
    return `iconify ${svgClass}`
  })

  const updateIcon = async (icon: string) => {
    if (unref(isLocal)) return

    const el = unref(elRef)
    if (!el) return

    await nextTick()

    if (!icon) return

    const svg = Iconify.renderSVG(icon, {})
    if (svg) {
      el.textContent = ''
      el.appendChild(svg)
    } else {
      const span = document.createElement('span')
      span.className = 'iconify'
      span.dataset.icon = icon
      el.textContent = ''
      el.appendChild(span)
    }
  }

  watch(
    () => props.icon,
    (icon: string) => {
      updateIcon(icon)
    }
  )
</script>

<template>
  <ElIcon :class="prefixCls" :color="color" :size="size">
    <svg v-if="isLocal" :class="getSvgClass" aria-hidden="true">
      <use :xlink:href="symbolId" />
    </svg>

    <span v-else ref="elRef" :class="$attrs.class" :style="getIconifyStyle">
      <span :class="getSvgClass" :data-icon="symbolId"></span>
    </span>
  </ElIcon>
</template>
